package Java_Concurrency_in_Practice.c8_5;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 如果不存在解答, ConcurrentPuzzleSolver不能很好的处理这种情况: getSolution将永远等待下去.</br>
 * 结束并发程序, 其中一种方法是: 记录活动任务的数量, 当该值为零时将解答设置为null.
 * @param <P> position
 * @param <M> move
 */
public class PuzzleResolver<P, M> extends ConcurrentPuzzleSolver<P, M> {

    public PuzzleResolver(Puzzle<P, M> puzzle, ExecutorService exec, ConcurrentHashMap<P, Boolean> seen) {
        super(puzzle, exec, seen);
    }

    private final AtomicInteger taskCount = new AtomicInteger();

    protected Runnable newTask(P p, M m, Node<P, M> n) {
        return new CountingSolverTask(p, m, n);
    }

    class CountingSolverTask extends SolverTask {

        public CountingSolverTask(P pos, M move, Node<P, M> prev) {
            super(pos, move, prev);
            taskCount.incrementAndGet();
        }

        @Override
        public void run() {
            try {
                super.run();
            } finally {
                if (taskCount.decrementAndGet() == 0) {
                    solution.setValue(null);
                }
            }
        }
    }
}
